package algo_lignes_sites.trt;

import algo_lignes_sites.data.Data_ls;
import algo_lignes_sites.params.Params_ls;
import commons.ihm.courbe.PanelCourbe;
import commons.logs.Logger;
import commons.utils.UtilsTime;
import java.awt.Color;
import javax.swing.JDialog;
import javax.swing.JOptionPane;

public class DialogTraitementLigneSite extends javax.swing.JDialog {

	private Data_ls data;
	private Params_ls params;
	private Worker worker;
	private boolean bStopCalcul;

	DialogDetailsTraitement dlg_DetailTraitement;

	private int nbTotalIter;

	public DialogTraitementLigneSite(Data_ls data) {
		initComponents();

		this.data = data;
		this.params = data.params;

		nbTotalIter = getNbIterTotal();

		tf_EchelleSouhaitee.setText("" + ((int) (1/params.echelleCible)));

		pb_ProgressionEchelle.setMinimum(0);
		pb_ProgressionEchelle.setMaximum(getNbIterTotal());
		pb_ProgressionEchelle.setValue(0);

		dlg_DetailTraitement = new DialogDetailsTraitement();
		dlg_DetailTraitement.setModal(false);
		dlg_DetailTraitement.initDisplay(nbTotalIter);
		adjustPositionOfDlgDetail();

		startCalcul();
	}

	// positionne la dlg de detail sous this
	private void adjustPositionOfDlgDetail() {
		dlg_DetailTraitement.setLocation(this.getLocation().x, this.getLocation().y + this.getHeight());
		dlg_DetailTraitement.setSize(this.getWidth(), dlg_DetailTraitement.getHeight());
	}

	
	private void startCalcul() {
		bStopCalcul = false;
		worker = new Worker(this);
		worker.start();
	}


	class Worker extends Thread {

		JDialog dlg;
		public Worker(JDialog dlg) {
			this.dlg = dlg;
		}

		@Override
		public void run() {
			UtilsTime.startTimer("Traitement complet");
			double echelleCourante_inv = 1/params.echelleInit;
			int numEtape = 0;
			while (echelleCourante_inv <= 1/params.echelleCible) {			
				if (bStopCalcul) {
					Logger.log_INFO1("Traitement arrêté par l'utilisateur");
					break;
				}
				traiteEtape (numEtape, echelleCourante_inv, false);
				numEtape++;
				echelleCourante_inv *= params.facteurIncrementEchelle;
			}
			// arrive a l'echelle finale, on remet une couche finale avec des paramètre qui peuvent êter différents
			if (!bStopCalcul)
				traiteEtape (numEtape, 1/params.echelleCible, true);

			UtilsTime.stopTimer("Traitement complet");
			addText(UtilsTime.getStringDuree("Traitement complet"));

			bStopCalcul = true;

			finalizeTraitement();
		}

		// bLast = true si c'est la dernière série d'itération (échelle finale)
		private void traiteEtape (int numEtape, double echelle_inv, boolean bLast) {
			addText("Etape n° " + (numEtape+1) + " echelle = 1 / " + (int)echelle_inv);

			data.setEchelleCarteCourante(echelle_inv);
			tf_EchelleEnCours.setText("" + ((int) echelle_inv));

			int nbIter = params.nbIterParEchelle;
			if (bLast) {
				nbIter = params.nbIterFinal;
				// Une augmentation de la force de respect de forme peut améliorer l'esthétique du traitement
				//  (ex a gauche de CURTI, la ligne 400 peut zigzager fort si pas cette option)
				params.poidsForce_RespectForme_PATH = params.poidsForce_RespectForme_PATH_final;
			}

			for (int i=0; i<nbIter ; i++) {
				if (bStopCalcul) break;
				int numIter = numEtape * params.nbIterParEchelle + i;
				data.step("Itération n°" + numIter);

				// détection de divergence du modèle
				if (data.hasDiverged()) {
					JOptionPane.showMessageDialog(dlg, "Le calcul a divergé.\nUne solution consiste à diminuer le pas de temps dans les paramètres avancés.", "Erreur durant le traitement", JOptionPane.ERROR_MESSAGE);
					bStopCalcul = true;
				}

				updateStats(numIter);
				setProgress(numIter);
			}
		}

		private void updateStats(int numIter) {
			dlg_DetailTraitement.updateDisplay(numIter, data);
		}
	}


	// Maj l'IHM de la DLG en fin de traitement
	private void finalizeTraitement() {
		pb_ProgressionEchelle.setValue(getNbIterTotal());
		button_StopCalcul.setText("Fermer la fenêtre");
	}

	private void addText( String txt) {
		Logger.log_INFO1(txt);
	}

	public void setProgress(int value) {
		// ATTENTION, on n'est pas dans l'EDT, mais tant pis
		pb_ProgressionEchelle.setValue(value);
	}

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        pb_ProgressionEchelle = new javax.swing.JProgressBar();
        tf_EchelleEnCours = new javax.swing.JTextField();
        jLabel7 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        tf_EchelleSouhaitee = new javax.swing.JTextField();
        button_StopCalcul = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        toggle_ShowDetails = new javax.swing.JToggleButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
        setTitle("Traitement");
        setResizable(false);
        addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentMoved(java.awt.event.ComponentEvent evt) {
                formComponentMoved(evt);
            }
        });

        pb_ProgressionEchelle.setRequestFocusEnabled(false);
        pb_ProgressionEchelle.setStringPainted(true);

        tf_EchelleEnCours.setEditable(false);

        jLabel7.setText("Echelle en cours");

        jLabel6.setText("Echelle finale");

        tf_EchelleSouhaitee.setEditable(false);

        button_StopCalcul.setIcon(new javax.swing.ImageIcon(getClass().getResource("/res/icons/croix_16.png"))); // NOI18N
        button_StopCalcul.setText("Stopper le calcul");
        button_StopCalcul.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                button_StopCalculActionPerformed(evt);
            }
        });

        jLabel1.setText("1 /");

        jLabel2.setText("1 /");

        toggle_ShowDetails.setText("Afficher détails traitement");
        toggle_ShowDetails.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                toggle_ShowDetailsActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                        .addComponent(pb_ProgressionEchelle, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(jLabel6)
                                .addComponent(jLabel7))
                            .addGap(18, 18, 18)
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                .addComponent(jLabel2)
                                .addComponent(jLabel1))
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                .addComponent(tf_EchelleEnCours)
                                .addComponent(tf_EchelleSouhaitee, javax.swing.GroupLayout.DEFAULT_SIZE, 100, Short.MAX_VALUE))))
                    .addComponent(button_StopCalcul)
                    .addComponent(toggle_ShowDetails))
                .addContainerGap(350, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel6)
                    .addComponent(tf_EchelleSouhaitee, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel1))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel7)
                    .addComponent(tf_EchelleEnCours, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel2))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(pb_ProgressionEchelle, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(toggle_ShowDetails)
                .addGap(17, 17, 17)
                .addComponent(button_StopCalcul)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

	private void button_StopCalculActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_button_StopCalculActionPerformed
		//le calcul est déjà terminé, le bouton sert alors à fermer la fenêtre
		if (bStopCalcul) {
			dlg_DetailTraitement.setVisible(false);
			dlg_DetailTraitement.dispose();
			setVisible(false);
			dispose();
			return;
		}

		//ici, on est en cours de calcul
		int ret = JOptionPane.showConfirmDialog(this, "Etes vous sûr de vouloir stopper le traitement ?\n(Vous ne pourrez plus le relancer sans recharcher et reparamétrer les données)", "Arrêt du traitement", JOptionPane.OK_CANCEL_OPTION);
		if (ret==JOptionPane.CLOSED_OPTION || ret==JOptionPane.CANCEL_OPTION)
			return;
		bStopCalcul = true;
	}//GEN-LAST:event_button_StopCalculActionPerformed

	private void toggle_ShowDetailsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_toggle_ShowDetailsActionPerformed
		if (toggle_ShowDetails.isSelected()) {
			toggle_ShowDetails.setText("Masquer détails traitement");
			dlg_DetailTraitement.setVisible(true);
		} else {
			toggle_ShowDetails.setText("Afficher détails traitement");
			dlg_DetailTraitement.setVisible(false);
		}
}//GEN-LAST:event_toggle_ShowDetailsActionPerformed

	private void formComponentMoved(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentMoved
		// on replace la dlg de detail bien en dessous de this
		adjustPositionOfDlgDetail();
	}//GEN-LAST:event_formComponentMoved

	private int getNbIterTotal() {
		return getNbIterTotal(1/params.echelleInit, 1/params.echelleCible, params.facteurIncrementEchelle, params.nbIterParEchelle, params.nbIterFinal);
	}

	static public int getNbIterTotal(double echelleInit_inv, double echelleCible_inv, double facteurAccroisEchelle, int nbIterParEchelle, int nbIterFinal) {
		int nbIterTotal = 0;
		double echelleCourante_inv = echelleInit_inv;

		if (facteurAccroisEchelle<=1.00001)
			return 0; // calcul impossible !
		
		while (echelleCourante_inv <= echelleCible_inv) {
			nbIterTotal += nbIterParEchelle;
			echelleCourante_inv *= facteurAccroisEchelle;
		}
		nbIterTotal +=  nbIterFinal;// arrive a l'echelle finale, on en remet encore une couche
		return nbIterTotal;
	}


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton button_StopCalcul;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JProgressBar pb_ProgressionEchelle;
    private javax.swing.JTextField tf_EchelleEnCours;
    private javax.swing.JTextField tf_EchelleSouhaitee;
    private javax.swing.JToggleButton toggle_ShowDetails;
    // End of variables declaration//GEN-END:variables


}

